﻿using System;
using System.ComponentModel;
using System.Text;
using System.Xml.Linq;
using Castle.ActiveRecord;
using Light.Framework.Model;
using Light.Utility;
using Light.Framework.Castle;


namespace Light.Weixin.Model
{
    /// <summary>
    /// 微信普通消息
    /// </summary>
    [Traceable]
    [ImportField]
    [ActiveRecord]
    [DisplayName("微信消息")]
    public class WxMsg : Entity
    {
        public WxMsg()
            : this(WxMsgType.Text)
        {
        }

        /// <summary>
        /// 默认构造函数
        /// </summary>
        public WxMsg(WxMsgType type)
        {
            MsgType = type;
        }

        /// <summary>
        /// 将xml消息转换为实体
        /// </summary>
        /// <param name="requestXml"></param>
        public WxMsg(string requestXml)
        {
            if (String.IsNullOrEmpty(requestXml))
            {
                throw new Exception("xml数据不能为空！");
            }

            XDocument doc = XDocument.Parse(requestXml);
            XElement root = doc.Element("xml");

            this.FromUserName = root.Element("FromUserName").Value;
            this.ToUserName = root.Element("ToUserName").Value;
            string type = root.Element("MsgType").Value.ToLower();
            string notsupport = "请登录 mp.weixin.qq.com 查看";

            if (type == "text")
            {
                this.MsgType = WxMsgType.Text;
                this.Content = root.Element("Content").Value.ToLower();
            }
            else if (type == "event")
            {
                this.MsgType = WxMsgType.Event;
                string eventName = root.Element("Event").Value.ToLower();

                if (eventName == "subscribe")
                {
                    //扫描带参二维码，参数在关注后可获取 
                    //<![CDATA[subscribe]]></Event><EventKey><![CDATA[qrscene_1010]]></EventKey>
                    this.MsgType = WxMsgType.Subscribe;
                    this.Content = eventName;
                    string eventKey = root.Element("EventKey").Value;
                    if (!String.IsNullOrEmpty(eventKey))
                        this.QRScene = eventKey.Split('_')[1];
                }
                else if (eventName == "unsubscribe")
                {
                    this.MsgType = WxMsgType.Unsubscribe;
                    this.Content = eventName;
                }
                else if (eventName == "templatesendjobfinish")
                {
                    this.MsgType = WxMsgType.TemplateSendJobFinish;
                    this.Content = root.Element("Status").Value.ToLower();
                }
                else if (eventName == "scan")
                {
                    //注意，用户关注后，才会触发Scan事件；
                    this.MsgType = WxMsgType.Scan;
                    this.Content = root.Element("EventKey").Value.ToLower();
                }
                else if (eventName == "click")
                {
                    this.MsgType = WxMsgType.Click;
                    this.Content = root.Element("EventKey").Value.ToLower();
                }
                else if (eventName == "view")
                {
                    this.MsgType = WxMsgType.View;
                    this.Content = root.Element("EventKey").Value;
                }
                else
                {
                    this.Content = root.Element("EventKey").Value.ToLower();
                }
            }
            else if (type == "voice")
            {
                this.MsgType = WxMsgType.Voice;
                this.Content = root.Element("MediaId").Value;
            }
            else if (type == "image")
            {
                this.MsgType = WxMsgType.Image;
                this.Content = root.Element("MediaId").Value;
            }
            else if (type == "video")
            {
                this.MsgType = WxMsgType.Video;
                this.Content = notsupport;//root.Element("MediaId").Value;
            }
            else if (type == "shortvideo")
            {
                this.MsgType = WxMsgType.ShortVideo;
                this.Content = notsupport; //root.Element("MediaId").Value;
            }
            else if (type == "link")
            {
                this.MsgType = WxMsgType.Link;
                this.Content = root.Element("Url").Value; ; //root.Element("MediaId").Value;
            }
            else
            {
                this.MsgType = WxMsgType.Other;
                this.Content = notsupport;
            }
        }

        /// <summary>
        ///类型
        /// </summary>
        [Property]
        [ImportField("消息类型")]
        public WxMsgType MsgType { get; set; }

        /// <summary>
        /// 发送人Openid
        /// </summary>
        [Property]
        [ImportField("发送人Openid")]
        public string FromUserName { get; set; }

        /// <summary>
        /// 发送人，不可能为null（微信用户，执行WxApp.ProcessMsg(WxMsg msg)后赋值）
        /// </summary>
        public WxUserInfo FromUser { get; set; }

        /// <summary>
        /// 接收人Openid
        /// </summary>
        [Property]
        [ImportField("接收人Openid")]
        public string ToUserName { get; set; }

        /// <summary>
        /// 内容
        /// </summary>
        [Property("FContent")]
        [ImportField("消息内容")]
        public string Content { get; set; }

        /// <summary>
        /// 二维码参数
        /// </summary>
        [Property]
        public string QRScene { get; set; }

        /// <summary>
        /// 是否已回复
        /// </summary>
        [Property]
        public bool IsAnswered { get; set; }

        /// <summary>
        /// 回复
        /// </summary>
        [Property]
        [ImportField("回复内容")]
        public string Answer { get; set; }

        /// <summary>
        /// 所属微信公众号
        /// </summary>
        [BelongsTo("WxApp_ID", NotFoundBehaviour = NotFoundBehaviour.Ignore)]
        public WxApp WxApp { get; set; }

        /// <summary>
        /// 用户信息
        /// </summary>
        [BelongsTo("WxUserInfo_ID", NotFoundBehaviour = NotFoundBehaviour.Ignore)]
        public WxUserInfo UserInfo { get; set; }

        /// <summary>
        /// 转换为Xml回复消息
        /// </summary>
        /// <returns></returns>
        public string ToResponseXml()
        {
            StringBuilder builder = new StringBuilder();
            builder.Append("<xml>");
            builder.Append("<ToUserName>" + this.FromUserName + "</ToUserName>");
            builder.Append("<FromUserName>" + this.ToUserName + "</FromUserName>");
            builder.Append("<CreateTime>" + DateTime.Now.Ticks.ToString() + "</CreateTime>");
            builder.Append("<MsgType>" + this.MsgType.ToString().ToLower() + "</MsgType>");

            if (this.MsgType == WxMsgType.Text)
            {
                builder.Append("<Content>" + this.Answer + "</Content>");
            }
            else if (this.MsgType == WxMsgType.Image)
            {
                builder.Append("<Image>");
                builder.Append("<MediaId>" + this.Answer + "</MediaId>");
                builder.Append("</Image>");
            }
            else if (this.MsgType == WxMsgType.Voice)
            {
                builder.Append("<Voice>");
                builder.Append("<MediaId>" + this.Answer + "</MediaId>");
                builder.Append("</Voice>");
            }
            else if (this.MsgType == WxMsgType.Video)
            {
                builder.Append("<Video>");
                builder.Append("<MediaId>" + this.Answer + "</MediaId>");
                builder.Append("<Title></Title>");
                builder.Append("<Description></Description>");
                builder.Append("</Video>");
            }
            else if (this.MsgType == WxMsgType.Music)
            {
                builder.Append("<Music>");
                builder.Append("<Title></Title>");
                builder.Append("<Description></Description>");
                builder.Append("<MusicURL></MusicURL>");
                builder.Append("<HQMusicUrl></HQMusicUrl>");
                builder.Append("<ThumbMediaId>" + this.Answer + "</ThumbMediaId>");
                builder.Append("</Music>");
            }
            else
            {
                builder.Append("<Content>" + this.Answer + "</Content>");
            }
            builder.Append("</xml>");


            return builder.ToString();
        }

        public override string ToString()
        {
            return string.Format("用户：{0} 内容：{1} 回复：{2}", FromUserName, Content, IsAnswered ? Answer : "等待回复");
        }

        protected override void ValidateRules()
        {
            this.AddValidateRules(!IsAnswered || IsAnswered && !String.IsNullOrEmpty(Answer), "请填写回复内容");
        }
    }
}
